package com.iqiyi.controller;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.iqiyi.common.R;
import com.iqiyi.domain.*;
import com.iqiyi.entity.MovieVo;
import com.iqiyi.service.*;
import io.swagger.annotations.ApiImplicitParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.*;

/**
 * @auther Z_zjl
 * @date 2022/12/17 15:27
 * @Description
 */
@RestController
@RequestMapping("movie")
@CrossOrigin(value = "http://localhost:8080")
@Slf4j
public class MovieController {

    @Value("${iqiyi.path}")
    private String basePath; // 拿到配置文件中设置的路径

    @Resource
    private MovieService movieService;
    @Resource
    private MovieCategoryService movieCategoryService;
    @Resource
    private CategoryService categoryService;
    @Resource
    private MovieActorService movieActorService;
    @Resource
    private RecommendTypeService recommendTypeService;

    /**
     * 电影列表接口
     * 该接口需要将所有电影以及相关联的类型、演员全部查出来
     * 将结果都包装到MovieVo类中(里面有演员列表 和 类型列表)
     * @return
     */
    @GetMapping("/findAll")
    public List<MovieVo> findAll(){
        //List<MovieVo> movies = movieService.findAll();
        List<MovieVo> movies = movieService.findAllMovieInfo();
        return movies;
    }


    /**
     * 编辑电影时（修改电影之前），需要将数据回显到页面上
     * 需要回显的数据有：电影的基本信息、该电影的类型、所有的电影类型
     * @return
     */
    @GetMapping("/edit")
    public Map<String,Object> editMovie(Integer movieId){
        Map<String, Object> dataMap = new HashMap<>();

        //TODO 1. 查出所有电影类型
        List<Category> allCategories = categoryService.list();
        //TODO 2.根据movieId查出电影
        Movie movie = movieService.getOne(Wrappers.lambdaQuery(Movie.class).eq(Movie::getId, movieId));

        List<Category> categoryList = new ArrayList<>();
        //TODO 3.在电影、类型中间表中查出对应的记录
        List<MovieCategory> movieCategoryList = movieCategoryService.list(Wrappers.lambdaQuery(MovieCategory.class).eq(MovieCategory::getMovieid, movie.getId()));
        //TODO 4.查出类型
        movieCategoryList.forEach(movieCategory -> {
            Category category = categoryService.getOne(Wrappers.lambdaQuery(Category.class).eq(Category::getId, movieCategory.getCategoryid()));
            categoryList.add(category);
        });
        // 将需要的数据包装到dataMap中
        dataMap.put("categoryList",categoryList);
        dataMap.put("allCategories",allCategories);
        dataMap.put("movie",movie);
        return dataMap;
    }

    /**
     * 修改电影接口
     * 按下修改键后将电影信息修改
     * @param movieVo
     * @return
     */
    @PostMapping("/saveMovie")
    @ApiImplicitParam(name = "categories", value = "categories", allowMultiple = true, dataTypeClass = List.class, paramType = "query")
    public String saveMovie(@RequestBody MovieVo movieVo){

        Movie movie = BeanUtil.copyProperties(movieVo, Movie.class);
        // 得到类型列表
        List<Category> categories = movieVo.getCategories();

        //TODO 1. 更新电影表中的记录
        boolean isUpdate = movieService.updateById(movie);
        //TODO 2. 先根据movieId删除电影、类型中间表的数据
        boolean isUpdate2 = movieCategoryService.remove(Wrappers.lambdaQuery(MovieCategory.class).eq(MovieCategory::getMovieid, movie.getId()));
        //TODO 3. 保存新的数据到电影、类型中间表
        if (categories.size() != 0){
            categories.forEach(category -> {
                MovieCategory movieCategory = new MovieCategory();
                movieCategory.setMovieid(movie.getId());
                movieCategory.setCategoryid(category.getId());
                movieCategoryService.save(movieCategory);
            });
        }
        return "已修改电影信息！";
    }

    /**
     * 电影删除接口
     * 电影表、电影类型中间表、电影演员中间表中的记录都要删除
     * @param movieId
     * @return
     */
    @GetMapping("/deleteMovie")
    public String deleteMovie(Integer movieId){
        //此方法是用xml实现的
        //movieService.deleteMovieById(movieId);

        //TODO 1. 删除电影表中的记录
        movieService.remove(Wrappers.lambdaQuery(Movie.class).eq(Movie::getId, movieId));

        //TODO 2. 删除电影、类型中间表的数据
        movieCategoryService.remove(Wrappers.lambdaQuery(MovieCategory.class).eq(MovieCategory::getMovieid, movieId));

        //TODO 3. 删除电影、演员中间表的数据
        movieActorService.remove(Wrappers.lambdaQuery(MovieActor.class).eq(MovieActor::getMovieid, movieId));

        return "电影已删除";
    }

    /**
     * 添加电影的接口
     * @param movieVo
     * @return
     */
    @PostMapping("/addMovie")
    @ApiImplicitParam(name = "categories", value = "categories", allowMultiple = true, dataTypeClass = List.class, paramType = "query")
    //public String addMovie(@RequestBody Movie movie,@RequestBody List<Category> categories){
    public String addMovie(@RequestBody MovieVo movieVo){

        Movie movie = BeanUtil.copyProperties(movieVo, Movie.class);
        //movie.setPic(basePath+movie.getPic()); // 传过来的是文件的名字
        movieService.save(movie);//先添加电影

        // 得到添加的这个电影的id
        int movieId = movieService.getOne(Wrappers.lambdaQuery(Movie.class).eq(Movie::getName, movie.getName())).getId();

        // 得到类型列表
        List<Category> categories = movieVo.getCategories();
        // 将信息保存到电影、类型的中间表里
        categories.forEach(category -> {
            MovieCategory movieCategory = new MovieCategory();
            movieCategory.setCategoryid(category.getId());
            movieCategory.setMovieid(movieId);
            movieCategoryService.save(movieCategory);
            });

        return "添加成功！";
    }

    /**
     * 播放电影接口
     * 需要返回当前电影的信息和推荐列表
     * @param movieId
     * @return
     */
    @GetMapping("/playMovie")
    public Map<String,Object> playMovie(Integer movieId){
        // 这两个基本方法是在xml里用sql实现的，如需要可直接用
        // movieService.findTop3ByActors(movieId);
        // movieService.findTop3ByCates(movieId);

        // 下面用mybatisplus实现
        Map<String,Object> dataMap = new HashMap();

        Movie nowMovie = movieService.getOne(Wrappers.lambdaQuery(Movie.class).eq(Movie::getId, movieId));
        dataMap.put("nowMovie",nowMovie);

        //查询RecommendType表得到isrecommend为1的记录，看当前的推荐方式是什么
        List<RecommendType> list = recommendTypeService.list(Wrappers.lambdaQuery(RecommendType.class).eq(RecommendType::getIsrecommend, 1));
        log.info("当前的推荐方式:{}",list);
        for (RecommendType r: list){
            // 如果id=1，说明按类型推荐。查出至多3条和当前电影相同类型的电影
            if (r.getId() == 1){

                //根据movieId查Movie和Category的中间表，用于得到该电影的类型
                List<MovieCategory> movieCategories = movieCategoryService.list(Wrappers.lambdaQuery(MovieCategory.class).eq(MovieCategory::getMovieid, movieId));

                //根据类型Id查Movie和Category的中间表，得到movieId（和传过来的movieId不能相同，自身也不能相同，用set接收）
                Set<Integer> set = new HashSet<>();
                for (MovieCategory mc:movieCategories){
                    List<MovieCategory> movieCategories1 = movieCategoryService.list(Wrappers.lambdaQuery(MovieCategory.class).eq(MovieCategory::getCategoryid, mc.getCategoryid()));
                    for (MovieCategory mc2:movieCategories1){
                        if (mc2.getMovieid() != movieId){
                            set.add(mc2.getMovieid());
                        }
                    }
                }
                //根据movieId查Movie表,装入3条记录
                List<Movie> sameTypeMovies = new ArrayList<>(3);
                for (int s: set){
                    if (sameTypeMovies.size() == 3)break;
                    Movie movie = movieService.getOne(Wrappers.lambdaQuery(Movie.class).eq(Movie::getId, s));
                    sameTypeMovies.add(movie);
                }
                dataMap.put("sameTypeMovies",sameTypeMovies);
            }

            // 如果id=2，说明按演员推荐。查出3条有当前电影主演的电影
            if (r.getId() == 2){
                // 根据movieId查Movie和Actor的中间表，得到相关记录
                List<MovieActor> movieActors = movieActorService.list(Wrappers.lambdaQuery(MovieActor.class).eq(MovieActor::getMovieid, movieId));
                //得到3个actorId（和传过来的movieId不能相同，自身也不能相同，用set接收）
                Set<Integer> set = new HashSet<>();
                for (MovieActor mc:movieActors){
                    List<MovieActor> movieActors1 = movieActorService.list(Wrappers.lambdaQuery(MovieActor.class).eq(MovieActor::getActorid, mc.getActorid()));
                    for (MovieActor ma:movieActors1){
                        if (ma.getMovieid() != movieId){
                            set.add(ma.getMovieid());
                        }
                    }
                }
                //根据movieId查Movie表,装入3条记录。直接指定大小懒得加分页了
                List<Movie> sameActorMovies = new ArrayList<>(3);
                for (int s: set){
                    if (sameActorMovies.size() == 3)break;
                    Movie movie = movieService.getOne(Wrappers.lambdaQuery(Movie.class).eq(Movie::getId, s));
                    sameActorMovies.add(movie);
                }
                dataMap.put("sameActorMovies",sameActorMovies);
            }
        }
        return dataMap;
    }
}
